package com.caregiver.watch.business.care.helper;

import com.caregiver.watch.business.care.enums.FenceStatus;
import com.caregiver.watch.business.care.model.dto.FenceLocation;
import com.caregiver.watch.business.data.model.po.HealthDeviceLocation;
import com.caregiver.watch.common.utils.collection.ListUtils;
import org.locationtech.jts.geom.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 示例功能：
 * 1. 定义一个多边形区域（经纬度点组成）
 * 2. 判断某个点是否在区域内
 * 3. 判断轨迹点是进入区域还是离开区域
 */
public final class GeoFenceCheckerHelper {

    // JTS 工厂类，用于创建几何对象
    private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();

    /**
     * 根据一组经纬度点创建多边形（经度在前，纬度在后）
     */
    private static Polygon createPolygon(List<FenceLocation> fenceLocations) {
        // 过滤掉无效的坐标点
        List<FenceLocation> coordinates =
                ListUtils.filter(fenceLocations, fenceLocation -> Objects.nonNull(fenceLocation.getLongitude()) && Objects.nonNull(fenceLocation.getLatitude()))
;        if (coordinates == null || coordinates.size() < 3) {
            throw new IllegalArgumentException("多边形至少需要3个坐标点");
        }

        Coordinate[] coords = new Coordinate[coordinates.size() + 1];
        for (int i = 0; i < coordinates.size(); i++) {
            FenceLocation fenceLocation = coordinates.get(i);
            coords[i] = new Coordinate(fenceLocation.getLongitude().doubleValue(), fenceLocation.getLatitude().doubleValue());
        }
        // 闭合多边形：首尾相同
        coords[coordinates.size()] = coords[0];

        return GEOMETRY_FACTORY.createPolygon(coords);
    }

    /**
     * 判断某个点是否在围栏内
     */
    private static boolean isPointInsideFence(double lon, double lat, Polygon fence) {
        Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(lon, lat));
        return fence.contains(point);
    }

    /**
     * 根据一系列轨迹点，判断轨迹最终的状态变化
     * @param healthDeviceLocations 轨迹点列表
     * @param fenceLocations 围栏定位信息
     * @return 轨迹变化状态
     */
    public static FenceStatus getTrackFenceStatus(List<HealthDeviceLocation> healthDeviceLocations,
                                                  List<FenceLocation> fenceLocations) {
        // 过滤无效的轨迹点
        List<HealthDeviceLocation> trackPoints =
                ListUtils.filter(healthDeviceLocations, location -> Objects.nonNull(location.getLongitude()) && Objects.nonNull(location.getLatitude()));
        if (trackPoints == null || trackPoints.size() < 2) {
            return FenceStatus.UNKNOWN;
        }
        Polygon fence = createPolygon(fenceLocations);
        // 起始点
        HealthDeviceLocation first = trackPoints.get(0);
        boolean startInFence = isPointInsideFence(first.getLongitude().doubleValue(), first.getLatitude().doubleValue(), fence);

        // 结束点
        HealthDeviceLocation last = trackPoints.get(trackPoints.size() - 1);
        boolean endInFence = isPointInsideFence(last.getLongitude().doubleValue(), last.getLatitude().doubleValue(), fence);

        // 状态判定逻辑
        if (!startInFence && endInFence) {
            return FenceStatus.ENTER; // 从外到内
        } else if (startInFence && !endInFence) {
            return FenceStatus.EXIT; // 从内到外
        } else if (startInFence) {
            return FenceStatus.INSIDE; // 一直在围栏内
        } else {
            return FenceStatus.OUTSIDE; // 一直在围栏外
        }
    }
}
